﻿using System;
using System.Web.UI;
using JQuery.WebKit.Base;
using JQuery.WebKit.WebCommon;
using JQuery.WebKit.WebCommon.Attributes;
using Newtonsoft.Json;

#region resources
[assembly: WebResource("JQuery.WebKit.JUpdater.JUpdater.js", "text/javascript")]
[assembly: WebResource("JQuery.WebKit.JUpdater.JUpdater.min.js", "text/javascript")]
[assembly: WebResource("JQuery.WebKit.JUpdater.jquery.json-2.2.js", "text/javascript")]
[assembly: WebResource("JQuery.WebKit.JUpdater.jquery.json-2.2.min.js", "text/javascript")]
[assembly: WebResource("JQuery.WebKit.JUpdater.BlockUI.js", "text/javascript")]
[assembly: WebResource("JQuery.WebKit.JUpdater.BlockUI.min.js", "text/javascript")]
#endregion

namespace JQuery.WebKit
{
    public enum ScriptType
    {
        Submit = 0,
        Refresh = 1
    }

    public class JUpdater : WebControlBase, INamingContainer
    {
        public event PipelineEventHandler Refresh;
        public event PipelineEventHandler Submit;
        public event EventHandler Load;

        private JUpdaterData _data;

        [JavaScript("progressControlID", Category = "options", DefaultValue = null)]
        public string ProgressControlID
        {
            get;
            set;
        }

        [JavaScript("errorContainerID", Category = "options", DefaultValue = null)]
        public string ErrorContainerID
        {
            get;
            set;
        }

        [JavaScript("deferLoad", Category = "options", DefaultValue = false)]
        public bool? DeferLoad
        {
            get;
            set;
        }

        [JavaScript("onGetSuccess", Category = "options")]
        public string OnGetSuccess { get; set; }

        [JavaScript("onPostSuccess", Category = "options")]
        public string OnPostSuccess { get; set; }

        [JavaScript("onGetError", Category = "options")]
        public string OnGetError { get; set; }

        [JavaScript("onPostError", Category = "options")]
        public string OnPostError { get; set; }

        [JavaScript("onComplete", Category = "options")]
        public string OnComplete { get; set; }

        [JavaScript("onError", Category = "options")]
        public string OnError { get; set; }

        [JavaScript("onBeginUpdate", Category = "options")]
        public string OnBeginUpdate { get; set; }

        public bool IsRefresh
        {
            get
            {
                return Page.IsRefresh && (string)Page.PageData["target"] == this.ClientID;
            }
        }

        public bool IsPostBack
        {
            get
            {
                return Page.IsPostBack && (string)Page.PageData["target"] == this.ClientID;
            }
        }

        public JUpdater()
            : base()
        {
        }

        private void SetDefaultValues()
        {
            if (!string.IsNullOrEmpty(OnGetSuccess))
            {
                if (!OnGetSuccess.StartsWith("function"))
                {
                    OnGetSuccess = string.Format("function(data, textStatus, request) {{ {0} }}", OnGetSuccess);
                }
            }
            if (!string.IsNullOrEmpty(OnPostSuccess))
            {
                if (!OnPostSuccess.StartsWith("function"))
                {
                    OnPostSuccess = string.Format("function(data, textStatus, request) {{ {0} }}", OnPostSuccess);
                }
            }
            if (!string.IsNullOrEmpty(OnGetError))
            {
                if (!OnGetError.StartsWith("function"))
                {
                    OnGetError = string.Format("function(request, textStatus, errorThrown) {{ {0} }}", OnGetError);
                }
            }
            if (!string.IsNullOrEmpty(OnPostError))
            {
                if (!OnPostError.StartsWith("function"))
                {
                    OnPostError = string.Format("function(request, textStatus, errorThrown) {{ {0} }}", OnPostError);
                }
            }
            if (!string.IsNullOrEmpty(OnComplete))
            {
                if (!OnComplete.StartsWith("function"))
                {
                    OnComplete = string.Format("function(event, request, textStatus) {{ {0} }}", OnComplete);
                }
            }
            if (!string.IsNullOrEmpty(OnBeginUpdate))
            {
                if (!OnBeginUpdate.StartsWith("function"))
                {
                    OnBeginUpdate = string.Format("function() {{ return {0}; }}", OnBeginUpdate);
                }
            }
            if (!string.IsNullOrEmpty(OnError))
            {
                if (!OnError.StartsWith("function"))
                {
                    OnError = string.Format("function(request, textStatus, errorThrown) {{ return {0}; }}", OnError);
                }
            }
        }

        public virtual void OnRefresh(Control sender)
        {
            if (Refresh != null)
            {
                Refresh(this, new PipelineEventArgs(sender));
            }
        }

        public virtual void OnSubmit(Control sender)
        {
            if (Submit != null)
            {
                Submit(this, new PipelineEventArgs(sender));
            }
        }

        public virtual void OnLoad()
        {
            if (Load != null)
            {
                Load(this, EventArgs.Empty);
            }
        }

        public void RefreshPanel()
        {
            string script = string.Format("$('#{0}').jupdater('refresh');", this.ClientID);
            this.Page.Resources.Add(new WebScriptResource(typeof(JUpdater), this.ClientID, ResourceType.Javascript, script, LoadEvent.DocumentReady));
        }

        public void SubmitPanel(string senderId)
        {
            string script = string.Format("$('#{0}').jupdater('submit', '{1}');", this.ClientID, senderId);
            this.Page.Resources.Add(new WebScriptResource(typeof(JUpdater), this.ClientID, ResourceType.Javascript, script, LoadEvent.DocumentReady));
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.RegisterJQueryResource("JQuery.WebKit.JUpdater.JUpdater.js");
            base.RegisterJQueryResource("JQuery.WebKit.JUpdater.jquery.json-2.2.js");
            base.RegisterJQueryResource("JQuery.WebKit.JUpdater.BlockUI.js");

            this.Attributes.Add("behavior", "updater");

            RegisterScripts();

            base.OnPreRender(e);
        }

        private void RegisterScripts()
        {
            _data = new JUpdaterData() { Page = this.Page.Request.Url.ToString() };
            string json = JsonConvert.SerializeObject(_data, Formatting.None);

            Control progressCtrl = null;
            if (!string.IsNullOrEmpty(ProgressControlID))
            {
                progressCtrl = this.Page.FindControlRecursive(ProgressControlID, IDType.Server);
            }
            if (progressCtrl == null)
            {
                progressCtrl = this.Page.FindControlRecursive(item => item.GetType() == typeof(JUpdateProgress));
            }
            if (progressCtrl != null)
            {
                this.Attributes.Add("progressID", progressCtrl.ClientID);
            }

            Control errorCtrl = null;
            if (!string.IsNullOrEmpty(ErrorContainerID))
            {
                errorCtrl = this.Page.FindControlRecursive(ErrorContainerID, IDType.Server);
            }
            if (errorCtrl == null)
            {
                Control updWithError = this.FindParent<JUpdater>(item => !string.IsNullOrEmpty(item.ErrorContainerID));
                if (updWithError != null)
                {
                    errorCtrl = this.Page.FindControlRecursive((updWithError as JUpdater).ErrorContainerID, IDType.Server);
                }
            }
            if (errorCtrl != null)
            {
                this.Attributes.Add("errorContainerID", errorCtrl.ClientID);
            }

            SetDefaultValues();
            string script = string.Format("$('#{0}').jupdater({1}, '{2}');", this.ClientID, this.GetJSProperties("options"), json);
            this.Page.Resources.Add(new WebScriptResource(typeof(JUpdater), this.ClientID, ResourceType.Javascript, script, true));
        }

        //private Color GetRandom()
        //{
        //    Random rnd = new Random();
        //    return Color.FromArgb(rnd.Next(0, 256), rnd.Next(0, 256), rnd.Next(0, 256));
        //}

        protected override void RenderContents(HtmlTextWriter writer)
        {
            if (DeferLoad.HasValue && DeferLoad.Value && Page != null && !Page.IsPostBack && !Page.IsRefresh)
            {
                return;
            }
            base.RenderContents(writer);
        }

        public string GetScript(ScriptType scriptType, string senderId)
        {
            switch (scriptType)
            {
                case ScriptType.Submit:
                    return string.Format("$('#{0}').jupdater('submit', '{1}');", this.ClientID, senderId);
                case ScriptType.Refresh:
                    if (!string.IsNullOrWhiteSpace(senderId))
                    {
                        return string.Format("$('#{0}').jupdater('refresh', '{1}');", this.ClientID, senderId);
                    }
                    else
                    {
                        return string.Format("$('#{0}').jupdater('refresh');", this.ClientID);
                    }
                default:
                    return string.Empty;
            }
        }
    }
}
